home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 038a / dosbasic.zip / FHELP.DOC < prev    next >
Text File  |  1990-12-19  |  30KB  |  620 lines

  1. ;
  2. ;DOS, Equipment and File Utilities
  3.  
  4. =======================================================================
  5.     Copyright (C) Copr. 1990 by Sidney J. Kelly
  6.             All Rights Reserved.
  7.             Sidney J. Kelly
  8.             150 Woodhaven Drive
  9.             Pittsburgh, PA 15228
  10.             home phone 412-561-0950 (7pm to 9:30pm EST)
  11.  
  12.      CompuServe   70043,1656
  13.      Genie        S.KELLY8
  14.  
  15. =======================================================================
  16.  
  17.         These routines provide information concerning the hardware/software
  18. environment.  A few routines are duplicated in PDS 7.1/QBX, though not with
  19. the same parameters.  Some routines provide information about the DOS
  20. status of a drive or file names.  Some routines even return information
  21. without needing ON ERROR GOSUB.  A fair number of hardware routines are
  22. provided.
  23.         Because I do not have access to PDS 7.x/QBX and its far string
  24. library, I believe that any of the routines that obtain input or make output
  25. to strings will not work correctly.  Some MASM code is shown below to
  26. demonstrate how to fix the routines so that they will do the same thing inside
  27. PDS 7.x/QBS.  Jim Mack has released some routines for PDS on COMPUSERVE MSSYS
  28. TRIMS.ASM.  It shows how to pass far strings inside PDS.
  29.  
  30.  =================================================================
  31.   DECLARE FUNCTION ACTUALEXTND% ()
  32.   Returns:
  33.         Actual amount of extended memory installed on 80286, 80386 or 80486
  34.         machine as stored in CMOS RAM
  35.         If clock battery is bad, will return a -1
  36.  
  37.  =================================================================
  38.   DECLARE FUNCTION ANSICHECK%()
  39.        IF ANSICHECK% THEN
  40.           PRINT "ANSI.SYS is installed."
  41.  
  42.   Source:  Disassembled COMMAND.COM Version 3.3 of CLS command
  43.                 xxxx:2B62h is the beginning of the routine
  44.  
  45.                 VERY FAST and NOT MESSY!!!!
  46.  
  47.  This is the same method that COMMAND.COM uses to test for ANSI.SYS
  48.  so every utility had better allow for this testing method.
  49.  
  50.   NOTE: PC Magazine's ANSI.COM even if turned off will still report ANSI.SYS
  51.         present, (it was planned that way so it would handle CLS).
  52.  
  53.  =================================================================
  54.   DECLARE SUB BEEPER   BEEPER
  55.   Primarily used to show you how to make sound in a somewhat machine
  56.   independent basis
  57.  
  58.  =================================================================
  59.  DECLARE FUNCTION CHECK87%()
  60.  Returns:
  61.          0 if no 80x87, or system equipment word not set.
  62.         87 if an 8087
  63.        -87 if 8087 emulation in use on an 80286 or 80386.  Because the
  64.              80287 has almost exactly the same instruction set as the
  65.             8087, few have felt a need to emulate the 80287.  I have not
  66.             seen an 80387 emulator in software.  The 80827 just includes
  67.             one new instruction (protected mode), nothing for use in
  68.             real mode.  80387 has transcendental math routines.*
  69.  
  70.        287 if an 80827
  71.        387 if an 80387 or 80487
  72.   More accurate than checking the equipment word.   QBX, Version 7
  73.   merely checks the equipment word to determine if an 80x87 is installed.
  74.   I guess that can be used as a software toggle.
  75.  
  76.   * Intel recently released an 80287 that has 80387 transcendental math
  77.     routines in it.  If someone sends me a new chip, I will write code
  78.     to test for it.
  79.  
  80.   Because of complaints about the traditional test with inexpensive clones
  81.   (See Jon Waterhouse letter in Byte, Nov. 1990, page 40)
  82.   routine first tests the equipment word in RAM bios.
  83.  
  84.  =================================================================
  85.  DECLARE FUNCTION DOSVER% ()
  86.  CALL DOSVER%
  87.  Returns DOS VERSION value as an integer, to get display value \ 100
  88.  E.g. DOS Version 3.3 is returned as 330
  89.  
  90.  =================================================================
  91.   DECLARE SUB DRVSPACE (DRIVE$,SPACE&)
  92.   checks if DRIVE$ <"A" or >"z", or if >"Z" & less <"a"
  93.   Drive of "@" gives the current drive
  94.   Invalid DRIVE$ gives a free space of 0
  95.   Note: DOS does not correctly adjust this if use JOIN or SUBST and
  96.   try to determine the size of a non-default drive.
  97.  
  98.  =================================================================
  99.   DECLARE SUB DRIVEALIAS ( ASSIGN%, DAPPEND%, NETWORK%, SHARE%)
  100.   CALL DRIVEALIAS( ASSIGN%, DAPPEND%, NETWORK%, SHARE%)
  101.   Purpose: To warn programmer that the logical drives may not be as they
  102.         seem, so if programmer desires to do some technical manipulation
  103.         he will be aware that it may not work.
  104.  
  105.  =================================================================
  106.   DECLARE SUB EQUIPMENT(ConvMem%,PrinterPorts%,ComPorts%)
  107.   Returns amount of Conventional Memory in KB           number of Parallel Ports
  108.           number of COM ports
  109.  
  110.  =================================================================
  111.   DECLARE SUB EXIST (FILNAME$, ErrCode%, Mode%)
  112.   CALL EXIST(FILENAME$+CHR$(0), ErrCode%, Mode%)
  113.   Filename$ must be an ASCII Null string (end in CHR$(0)).
  114.   Filename$ can not be a TYPEd string or a variable in a string array
  115.   because there is a chance that string will be outside DGROUP.  String
  116.   cocentenation is used to make sure it is in DGROUP.
  117.  
  118.   Mode%:
  119.        =  0 if just want to see if file exits
  120.        <> 0 if want to see if can read and write to file
  121.  
  122.   Returns ErrCode%    = 0 (False) if no error
  123.                       = True if an error,
  124.   Codes:
  125.        -1 = string wrong length
  126.         2 = file not found
  127.         3 = path not found
  128.         4 = no free handles
  129.         5 = access denied          (tried to read a subdirectory)
  130.        12 = invalid access code    (wont see this unless Mode% <> 0)
  131.        20 = Write protect error    (wont see this)
  132.        21 = Invalid drive
  133.        22 = Drive not ready        (floppy drive door open)
  134.        23 = unknown command
  135.        24 = CRC error
  136.        25 = Bad request structure
  137.        26 = Seek error
  138.        27 = Unknown disk format
  139.        28 = Sector not found
  140.        29 = Printer out of paper   (shouldn't see this)
  141.        30 = Write fault            (shouldn't see this)
  142.        31 = Read fault
  143.        32 = General, non-specific error (usually a network drive error)
  144.        35 = Invalid Disk Change    (shouldn't see this)
  145.  
  146.  =================================================================
  147.   DECLARE FUNCTION FINDDRIVES% ()
  148.   Returns number of current logical drives w/o any errors
  149.  
  150.   Because LASTDRIVE default value = 5, it is likely that
  151.   number of logical drives will be less than LASTDRIVE in CONFIG.SYS
  152.   This routine will miss a drive if there are gaps between logical drives
  153.   as can occur if SUBST is used.
  154.  
  155.  =================================================================
  156.   DECLARE SUB FLOPPYREADY (DRIVE$, ErrCode%)
  157.   Tests if floppy drive is ready, on a one floppy system
  158.   treats drive B: as equivalent to drive A:
  159.   ErrCode
  160.          128 = Time Out Error           80 = Track error
  161.          -1  = Drive$ is not valid
  162.           0  = All a.o.k.
  163.   Note : A critical error routine is not necessary for this routine to work
  164.  
  165.  =================================================================
  166.   DECLARE SUB FLOPPYDRIVES(NumDrives%)
  167.   Returns number of physical floppy drives in system
  168.  
  169.  =================================================================
  170.   DECLARE FUNCTION GETCPU% ()
  171.   Checks for CPU type
  172.   Returns:
  173.         88 for 8088
  174.         86 for 8086
  175.         20 for NEC V20
  176.         30 for NEC V30
  177.         186 for 80186 or 80188 (I have never seen an 80188 so no special test)
  178.         286 for 80286
  179.         386 for 80386DX or 80386SX
  180.         386 for 80486.  I offer no special test for 80486.
  181.  
  182.  =================================================================
  183.   DECLARE SUB GETCURRENTNAME (FName as STRING * 64, FileLength%)
  184.   Returns current filename for dos version 3.xx and above
  185.   if LEN(FName$) <> 64 then returns a FileLength% of -1
  186.  
  187.   FName$ can not be a TYPEd string or a variable in a string array
  188.   because there is a chance that string will be outside DGROUP.
  189.   This routine assumes that FName$ is a near string.
  190.   Function returns an error if DOS version < 3.xx since function is not
  191.   supported for that version.
  192.  
  193.  =================================================================
  194.  DECLARE SUB GETDOSVER (VERSION$)
  195.             VERSION$=SPACE$(4)
  196.             CALL GETDOSVER(VERSION$)
  197.  Returns DOS Version as a string
  198.  
  199.  =================================================================
  200.   DECLARE SUB GETDRIVE(DRIVE$)
  201.   CALL GETDRIVE(DRIVE$)
  202.   Returns current drive name
  203.   If LEN(DRIVE$)=0 then nothing happens
  204.  
  205.   Assumes that DRIVE$ is a near string, not TYPEd or part of a far string
  206.   array.  In other words, assumes DRIVE$ is in DGROUP
  207.  
  208.  =================================================================
  209.   DECLARE SUB GETFULLPATH (PATH$, PATHLEN%)
  210.   Returns current subdirectory path, with Drive:\, e.g. "A:\"
  211.   if LEN(Path$) <>  67 then returns a pathlen% of -1
  212.  
  213.   PATH$ can not be a TYPEd string or a variable in a string array   because there is a chance that string will be outside DGROUP.
  214.   This routine assumes that Path$ is a near string.
  215.  
  216.  =================================================================
  217.   DECLARE SUB GETSUB (PATH AS STRING * 64, PATHLEN%)
  218.   Returns current subdirectory path, without Drive:\, (i.e. no "A:\")
  219.   if LEN(Path$) not = to 64 then returns a pathlen% of -1
  220.  
  221.   PATH$ can not be a TYPEd string or a variable in a string array
  222.   because there is a chance that string will be outside DGROUP.
  223.   This routine assumes that Path$ is a near string.
  224.  
  225.  =================================================================
  226.   DECLARE SUB HARDDRIVES(NoDrives%)
  227.   Returns number of physical hard disks in system
  228.  
  229.  =================================================================
  230.   DECLARE SUB KILLPRINT (LptNum%)
  231.         CALL KILLPRINT(LptNum%)
  232.  
  233.   Halts LptNum%, by resetting and purging buffer. Printer reset to defaults
  234.   all non-default formats lost.  Will do nothing if errors noted, printer
  235.   is not busy.
  236.  
  237.  =================================================================
  238.   DECLARE FUNCTION MEM2INT% (SegAddress%,OffAddress%)
  239.   Reads word from memory and returns an integer value
  240.   Faster than PEEK(High_byte) * 256 + PEEK(Low_byte)
  241.  
  242.  =================================================================
  243.   DECLARE SUB MEM2STRING (TEXT$,SegAddress%,OffAddress%)
  244.   Reads bytes from memory and stores them into a string
  245.   number of bytes transferred is = LEN(Text$)
  246.   Assumes string is in near data (DGROUP) & not a fixed length string
  247.   or a user defined TYPE.
  248.  
  249.  =================================================================
  250.   DECLARE SUB OTHERMEMORY(EXTENDED%,EXPANDED%,XMS%)
  251.   Returns size of extended, expanded, and XMS memory.
  252.   Extended = only size that BIOS reports is free
  253.   Expanded = total installed.
  254.   XMS      = total installed.
  255.   Uses the rom ID byte approach to determine if extended memory supported.
  256.  
  257.  =================================================================
  258.   DECLARE SUB OTHEROPER (DPMI%, WINDOWS%, DESQ%)
  259.   CALL OTHEROPER(DPMI%, WINDOWS%, DESQ%)
  260.   Purpose: Checks if DPMI, or MS Windows or Quarterdeck DESQVIEW is active
  261.   Returns:
  262.         For each variable that exists -1
  263.         Else if multitasking environment does not exist then returns 0
  264.         Returns 0 if used with DOS versions < 3.x
  265.  
  266.  =================================================================  DECLARE FUNCTION PRINTRDY%(Lpt%)
  267.   Input:
  268.         Lpt% gives portnumber to test
  269.         Lpt%=1 for LPT1:, 2 for LPT2:, etc
  270.  
  271.   Returns:
  272.          0 if not ready
  273.         -1 (True) if ready
  274.  
  275.  =================================================================
  276.   DECLARE SUB PRINTSCREEN%(Mode%, Error%)
  277.   IF Error% THEN
  278.         printer error
  279.   else
  280.         all o.k.
  281.   end if
  282.  
  283.   Input:  0 = turn off printscreen key
  284.           1 = printscreen, then shut down key again
  285.   Prints to LPT1
  286.  
  287.  =======================================================================
  288.   DECLARE SUB REVERSESTRING (A$)
  289.   will reverse A$
  290.  
  291.   DECLARE SUB LEFTROTATE (A$)
  292.   will rotate a string one character to the left
  293.  
  294.   DECLARE SUB RIGHTROTATE (A$)
  295.   will rotate a string one character to the right
  296.  
  297.  =================================================================
  298.   DECLARE SUB SETDRIVE (DRIVE$,ErrCode%)
  299.   no change occurs if DRIVE$ <"A" or >"z", or if >"Z" & less <"a"
  300.   Returns   ErrCode% =  0 (False) if no errors
  301.                      = -1 (True)  if errors
  302.   error checking includes range check and real test if a change occurred
  303.  
  304.  =================================================================
  305.   DECLARE SUB SUBEXIST (PATH$+CHR$(0),ErrCode%)
  306.   Returns ErrCode%  =  0  (False) if no errors,
  307.                     = -1  (True)  if errors
  308.   If a drive change is required, subdirectory on other drive will be made
  309.   the "current" subdirectory on that other drive.
  310.  
  311.   PATH$ cannot be a TYPEd string or a variable in a string array
  312.   because there is a chance that string will be outside DGROUP.  String
  313.   cocentenation is used to make sure it is in DGROUP.
  314.  
  315.  =================================================================
  316.   DECLARE SUB SUBSTDRIVE (Drive$,ErrCode%)
  317.   CALL SUBSTDRIVE(Drive$,ErrCode%)
  318.  
  319.   Input:         Drive$ = letter between A to Z
  320.         If Drive$ ="" or is outside range, assume it is a request for
  321.         default drive information.
  322.  
  323.   Purpose: To warn programmer that the logical drives may not be as they
  324.         seem, so if programmer desires to do some technical manipulation
  325.         he will be aware that it may not work.
  326.  
  327.   Returns:
  328.         0 = o.k.
  329.         1 = invalid drive
  330.         2 = SUBST active on drive
  331.  
  332.  =================================================================
  333.   DECLARE SUB TRUENAME (OrigFile$+CHR$(0), TrueFName$, FileLength%)
  334.   Purpose:
  335.       Allows user to test for SUBST, ASSIGN, and JOIN using an
  336.       undocumented call for DOS Version 3.xx and above
  337.       The returned name will contain technically correct Drive: and Path
  338.       information.  However, the OrigFile$ is not checked so ? and * may be
  339.       used, the OrigFile$ may even be nonexistent.
  340.  
  341.   Shortcuts:
  342.   OrigFile$ = "." to obtain current drive & subdirectory name
  343.   OrigFile$ = ".." to obtain immediate parent drive & subdirectory name
  344.  
  345.   Usage:
  346.       TrueFName$ = STR$(67,0)
  347.       CALL TRUENAME(OrigFile$ + CHR$(0), TrueFName$, FileLength%)
  348.       IF FileLength% = -1 THEN
  349.            Error
  350.       ELSE
  351.            TrueFName$=LEFT$(TrueFName$, FileLength%)
  352.       END IF
  353.  
  354.  =================================================================
  355.  
  356.           QBASIC-MASM Interface Theory:
  357.           Generally QBASIC only keeps simple variables, (INT,
  358. LONGINT, SINGLE and DOUBLE, and STRINGS) in DGROUP.  Arrays and
  359. TYPE records are usually kept outside DGROUP, with only the
  360. STRING Descriptor or the undocumented Array descriptor kept in
  361. DGROUP.  Thus, the library routines assume that all information
  362. passed from simple variables is information about a near (DGROUP)
  363. address.  If we pass simple integers to MASM routines, and don't
  364. care to have MASM change those variables, we use BYVAL to send
  365. the information to MASM.  BYVAL speeds up variable access by a
  366. factor of two.  If we want to have MASM send information back
  367. about multiple variables, we must pass the address information
  368. for the variables without using BYVAL.  If we use arrays, we must
  369. use a combination of BYVAL & VARSEG and BYVAL & VARPTR to get the
  370. information we need to manipulate the information inside the
  371. arrays.  VARSEG and VARPTR are necessary because there is a very
  372. great chance that the arrays will be stored as far data (i.e. not stored in DGROUP).  If you must get an array in DGROUP, put the
  373. array in COMMON.
  374.           Text strings are sent by QBASIC as near address
  375. (relative to DS and DGROUP).  The fist value in the descriptor is
  376. the length of the string.  The second value is the offset address
  377. inside DGROUP.  Fixed length strings and TYPE record strings are
  378. not referenced with string descriptors.  For that reason, I don't
  379. allow such strings as variables in my routines.
  380.           PDS/QBX Version 7.x stores strings in FAR DATA, outside
  381. DGROUP.  Special routines are offered in the programmer's package
  382. to find address and length of far strings.  Not having access to
  383. that program (insufficient liquid assets), I can't suggest work
  384. arounds (I am sure that there are some library routines that will
  385. give you access).  My guess is that string input will work if the
  386. following format is used
  387.           Inside QBX:
  388.           DECLARE SUB xx(BYVAL SEGADD%, BYVAL OFFADD%, BYVAL
  389. LENGTH%, ...)
  390.           CALL xx(SSEG(A$), SADD(A$), LEN(A$), ...
  391.  
  392.           Inside MASM:
  393.           .code
  394.  
  395.           STRING SEGMENT AT 0h  ;used only for MASM assumptions
  396.           STRING ENDS           ;no code is generated.
  397.  
  398. xx PROC FAR BASIC USES ...,SEGADD:WORD, OFFADD:WORD, LENGTH:WORD
  399.           Push  DS
  400.           ...
  401.  
  402.           Mov   SI,OFFADD       ;offset of string
  403.           Mov   CX,LENGTH       ;length of string
  404.           Mov   AX,SEGADD       ;segment address of far string
  405.                                 ;segment
  406.           Mov   DS,AX
  407.  
  408.           Assume        DS:STRING   ;note lose access to stack
  409. when change DS
  410.           ...
  411.           Pop   DS
  412.           Assume DS:@data
  413.           ...
  414.           Ret
  415.           xx ENDP
  416.           END
  417.           Another approach, which I have not tested is to rely on
  418. the library routines included inside the QBX environment.
  419.  
  420.           Use the following library calls:
  421.           EXTRN StringAddress:FAR
  422.           EXTRN StringLength:FAR
  423.  
  424. How to use StringLength   (must clear direction flag CLD):
  425. Basic program must pass address of string descriptor on stack
  426. Push    StringDescriptor  ; push it back on stack
  427. call StringLength         ; call routine
  428. length returned in AX
  429.  
  430. How to use StringAddress (must clear direction flag CLD):
  431. Basic program must pass address of string descriptor on stack
  432.  
  433. Push    StringDescriptor   ; push it back on stack
  434. call StringAddress         ; call routine
  435. address returned in DX:AX  ; DX has segment address, AX has
  436.                            ; offset
  437.  
  438.           QBASIC requires that MASM preserve BP, SI, DI, DS, and
  439. keep the direction flag clear (CLD).  All these routines do this.
  440. You will note that MICROSOFT'S CALL INTERRUPT routines do not
  441. save BP (apparently to give you access to some EGA VGA palette
  442. and character font selection routines in the BIOS), and thus will
  443. crash if a critical error occurs.  MICROSOFT offers a replacement
  444. routine that overcomes this error by preventing any change to BP.
  445. You should get it if you don't already have it.
  446.           The choice of defining MASM routines as SUB's or
  447. FUNCTION's depends on whether you want to get information from
  448. MASM in DX:AX (the format for FUNCTIONs), or if the MASM routine
  449. either sends back no information or more than one variable (the
  450. format for SUBs).  For simple one variable routines when MASM is
  451. just returning a value, use FUNCTIONs.  To use such functions
  452. inside QBASIC you must either assign the value of the function to
  453. a QBASIC variable or use 1) IF ... THEN statements (C style), or
  454. 2) PRINT statements.  For everything else use SUBS.
  455.           Note due to an error in the QBASIC text parser, always
  456. use the CALL keyword to call the library routines if there is any
  457. chance that you will use a colon as a separator on a line AND the
  458. library routine does not take any parameters.  Without the CALL
  459. keyword, the QBASIC parser assumes that the routine name followed
  460. by a colon is intended as a line label, and not as a SUB name.
  461. You must use CALL if you will use a SUB that does not need any
  462. parameters and will follow that SUB name by a colon.
  463.           MASM Theory:
  464.           The MASM routines were designed to be compiled with MS
  465. QUICK ASSEMBLER, using simplified segment names.  They should
  466. compile with MS MASM 5.1 and above.  The DOSSEG keyword might not
  467. be supported by your version of MASM, so use the MASM keyword
  468. that arranges the segments in DOS order, rather than ALPHA order.
  469. If you use TASM with QUIRKS (IDEAL too?) you should be able to
  470. compile these programs with TASM.  Because A86 does not make MS
  471. .OBJ files, you probably cannot use it.  The same may be true
  472. with OPTASM.  The @@, @f, @b are local labels used so I can skip
  473. ahead without having to think up unique names.  Don't use @@, @f,
  474. @b inside MASM Macros, use LOCAL alphanumeric names instead.
  475. MASM too easily can lose track of which local label you mean.
  476.           The simplified directives really save time when you
  477. have to identify variables on the stack, and push and pop
  478. variables.  I use the full PROC function and the regular PROC keywords interchangeably.  Full PROC format is not necessary when
  479. there is no need to address variables on the stack (i.e. no need
  480. to change BP to address the stack) and the QBASIC routine is
  481. described as a FUNCTION or a SUB that does not take or return
  482. parameters..
  483.           The EVEN directive is used to word align loops for
  484. 80286 and 80386 machines.  EVEN inserts NOPS as necessary to word
  485. align loops.  The QBASIC BYVAL directive is used to get
  486. information directly from QBASIC without having to use [BX] or
  487. [SI] to fish out the correct information.  To allow for
  488. compatibility with the 8088 chip, shifts rather than MULs are
  489. used for speed.  I use .code to store most of my variables to
  490. save space in DGROUP, which is comparatively tiny and easily
  491. filed with string data.
  492.           To program in OS/2 .code segment variables are
  493. "verbotten", and you must use local variables on the stack.  I
  494. don't have access to the OS/2 DOS compatibility box, so I don't
  495. know how these routines would work under OS/2.  I am certain that
  496. none of these routines would work smoothly under protected mode
  497. because they often access the BIOS or the hardware.
  498.  
  499.  
  500. Bibliography:
  501.         General DOS/BIOS routines:  Ray Duncan and Peter Norton's
  502. programming books.  If you can only afford one book, get Duncan's.
  503. Duncan, "Advanced MS-DOS Programming" (2d Ed. Microsoft 1988).  Very
  504. easy to read and to refer to specific routines.  The text is very well
  505. formatted for easy reference.
  506.         Norton, "The New Peter Norton Programmer's Guide to the IBM PC
  507. and PS/2" (Harper & Row 1988).  A book designed to help you visualize
  508. what is going on.  Having been "burned" by writing a book on the PC
  509. Junior, and experienced the agony of hardware incompatibilities in
  510. writing the Norton Utilities, Peter wants everybody to use the bios and
  511. documented DOS routines.
  512.         Bradley, "Assembly Language Programming for the IBM Personal
  513. Computers" (Prentice Hall 1984).  Good technical descriptions of the
  514. original PC.  Only book I have seen that has really shown how to switch
  515. displays, manipulate DMA, make sound, and manipulate floppy disk drives
  516. at the PORT level (teaches you why we have BIOS and DOS routines).  Good
  517. book on the 8087.  Probably now out of print.  I bought my copy at a
  518. book store that sells remainders.
  519.         DOS Programming:
  520.         Detteman, "DOS Programmer's Reference (2d Ed. Que 1989).
  521. Excellent book with a very helpful look at undocumented DOS.  Doesn't
  522. preach about not using undocumented DOS as does Peter Norton.   Goes
  523. "mano a mano" with DOS.  You should read that material for a complete
  524. discussion of the undocumented calls contained in my routines.
  525.         Waite Group "Dos Developer's Guide" (2d Ed Howard Sams 1989).
  526. Good book on Expanded memory and math chips.  Several good discussions
  527. of the undocumented DOS functions.  Such a big book, that you feel you
  528. got your money's worth based just on weight.
  529.         General Programming:
  530.         Holzner, "PS/2-PC Assembly Language"  (Brady 1989)  Good
  531. introduction to assembly language programming.  In many respects much better than Holzner, "Advanced Assembly Language on the IBM PC" (Brady
  532. 1987).
  533.         Tischer, "PC System Programming for Developers" (ABACUS 1989).
  534. Good technical survey of PC/AT systems.  Comes with a lot of programs
  535. showing how to do useful things in MASM, GWBASIC, PASCAL and C.  The
  536. only shortcoming is that the book is printed on very cheap paper.  One
  537. of the few books to show register usage of DOS and BIOS routines
  538. (important so you can save variables in registers rather than in memory
  539. or pushed on the stack.)  Doesn't discuss DOS Version 4 in an integrated
  540. fashion.  Such a big book, that you feel you got your money's worth
  541. based just on weight.
  542.         Young, "Inside DOS: A Programmer's Guide", (Sybex 1990).  Good
  543. source of MASM code, with a primary emphasis on C (The MASM code is
  544. similar for both C and QBASIC).  A reprint of "MS DOS Advanced
  545. Programming" (Sybex 1988).  (I didn't discover this until I purchased
  546. both).
  547.         Wyatt, "Using Assembly Language" (2d Ed. QUE 1989).  Some decent
  548. video routines.  No useful description of VGA.  EGA routines are
  549. primitive.  Good insight into programming for high level languages.
  550. Complete listing of all the Intel keywords, but reads too much like an
  551. Intel-English dictionary.  Most of the examples in the keyword section
  552. are not really helpful and the ASCII math routines are not well
  553. described.  One major programming feature dropped from the 1st edition
  554. was the AT keyboard programming routines.  Does this mean AT keyboards
  555. are only marginally compatible on the hardware level?  Feedback please.
  556.         QBASIC Programming:
  557.         Goodwin, "QuickBASIC Advanced Programming Tools" (MIS 1989).  A
  558. much better book for QBASIC code (sorting, popup windows, dropdown
  559. windows and menubar programs) than for MASM code.  The MASM code relies
  560. on video bios to do things (which is slow, though always compatible).
  561. Moreover, screens are stored in STRINGs rather than arrays, which
  562. greatly limits the usefulness of his MASM routines.  (I agree storing
  563. screens in arrays takes more work).  A programmer can have access to
  564. several hundred KB of far data in arrays, while he can only have access
  565. to 30 to 40kb of precious string space in DGROUP.  PDS 7.1 gives access
  566. to about 190(?) kb of string space using far strings.  Goodwin's book
  567. was written before PDS was released.
  568.         Lesser,  "Advanced Quickbasic 4.0 Language Extensions with
  569. Modular Tools" (Bantam 1988).  This is how I learned about MASM/QBASIC
  570. programming.  Talks more about ideas that were important for QBASIC
  571. Version 3.0 -- MASM pre-version 5.1  (before simplified directives) than
  572. for QBASIC Version 4.x.  BELIEVES in structured programming.  Not too
  573. many hardware insights even though hardware insights are necessary for
  574. fast video programming.  Offers generally sound advice.
  575.         Microsoft, "QuickBasic Toolbox"  Generally, useful collection of
  576. routines.  Very speedy string routines, some good formatting and a good
  577. set of long int days between dates routines.  Some little insight into
  578. Quick C - Basic interfacting using Quick C library routines.  The DOS
  579. InterruptX routines are generally useful, however, they do not warn of a
  580. problem inside QBASIC that can cause QBASIC to lock up.  The error
  581. occurs if a critical error (typically disk error) occurs inside a Call
  582. Interrupt/InterruptX routine.
  583.         Reason for error: Because the Microsoft supplied version of that
  584. routine allows the programmer to change BP, any critical error causes QBASIC to get lost.  All smart programmers should obtain, from
  585. Microsoft's on-line knowledgebase on GENIE and COMPUSERVE, a copy of the
  586. revised routine and NOCOM.OBJ (makes some programs smaller by turning
  587. off all of QBASIC overhead associated with the COM ports) from
  588. Microsoft.  The revised Interrupt/InterruptX routines prevents any
  589. change to BP at the cost of a minor loss of funtionality in EGA/VGA font
  590. routines.
  591.         Shammas, "QuickBASIC- Programming Techniques and Library
  592. Development" (M&T Publishing 1988).  Good QBASIC code.  Some of the
  593. string routines are fast.  He has some BTREE and high level math
  594.  
  595. What's available:
  596.         VIDBASIC - A selection of text mode video routines.  Freeware.
  597. The library allows the user to select, move, switch, change, save,
  598. restore, draw boxes, and write with lightening speed.  MASM .ASM code,
  599. .OBJ, and a demo routine with source is included.  Uploaded by author on
  600. GENIE and COMPUSERVE.
  601.         KEYBASIC - A selection of Microsoft Compatible Mouse and
  602. Keyboard utilities.  Text mode mouse utilities.  Fast mouse utilities.
  603. Turn off CONTROL-BREAK so you can use LINE INPUT$ without error if user
  604. pushes the Control-Break key.  Freeware. MASM .ASM code, .OBJ, and a
  605. demo routine with source is included.  Uploaded by author on GENIE and
  606. COMPUSERVE.
  607.  
  608.         I don't anticipate I will do much more with any of these three
  609. libraries.  My next effort is to make menu environment similar to the
  610. environment inside QuickBasic, using the building blocks I have created.
  611. After that, I will probably try to figure out Quick C and convert much
  612. of the library to Quick C format.  I figure by the time I begin to
  613. understand Quick C, an OOPS form of Quick Basic will come out and much
  614. of my work will be for naught.
  615.         As always, constructive criticism is desired.  These libraries
  616. were released as Freeware to encourage a sharing of ideas.  If you have
  617. something to say, I welcome your comments.  With application programs
  618. there appears to be a significant and speedy exchange of ideas,
  619. programmers, on the other hand, seem to move at a much slower pace, with
  620. Jim Mack being the notable exception.